package net.hn.hnms.biz.energy.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ReflectUtil;
import net.hn.hnms.sys.system.api.RemoteUserService;
import net.hn.hnms.sys.system.api.model.LoginUser;
import org.springframework.context.ApplicationContext;

import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created on 2022/8/17.
 *
 * @author ly
 * @desc:
 */
public class BaseService<T, V> {

    private static String[] IGNORE_DATE = new String[]{"planStartDate", "planEndDate"};

//    protected String generatePlanName(String code,Date now) {
//        PlanDateType planDateType = PlanDateType.getByCode(code);
//        return planDateType.getDesc() + DateUtil.format(now, planDateType.getPlanNameFormat());
//    }
//
//    protected String generatePlanCode(String code,Date now) {
//        PlanDateType planDateType = PlanDateType.getByCode(code);
//        return DateUtil.format(now, planDateType.getPlanNameFormat());
//    }

    /**
     * 参数复制
     *
     * @param req
     * @param obj
     * @param planType
     */
//    protected void copyProperties(Object req, Object obj, String planType) {
//        copyProperties(req, obj, planType, IGNORE_DATE[0], IGNORE_DATE[1]);
//    }


    /**
     * 参数复制
     *
     * @param req
     * @param obj
     * @param planType
     * @param ignoreStartDate
     * @param ignoreEndDate
     */
//    protected void copyProperties(Object req, Object obj, String planType, String ignoreStartDate, String ignoreEndDate) {
//        BeanUtil.copyProperties(req, obj, ignoreStartDate, ignoreEndDate);
//        Date startDate, endDate;
//        if (StrUtil.equals(planType, PlanDateType.DAY.getCode())) {
//            startDate = DateUtil.beginOfDay(DateUtil.parseDate(Convert.toStr(ReflectUtil.getFieldValue(req, ignoreStartDate)) ));
//            endDate = DateUtil.endOfDay(startDate);
//        } else {
//            startDate = DateUtil.parseDate(Convert.toStr(ReflectUtil.getFieldValue(req, ignoreStartDate)) + PlanConstants.MONTH_BEGIN);
//            endDate = DateUtil.endOfMonth(startDate);
//        }
//        if (startDate.after(endDate)) {
//            throw new HuaNengException(Constants.FAIL, "计划开始时间不能在计划结束时间之后");
//        }
//        ReflectUtil.setFieldValue(obj, ignoreStartDate, startDate);
//        ReflectUtil.setFieldValue(obj, ignoreEndDate, endDate);
//    }

    /**
     * 参数复制 toVo
     *
     * @param req
     * @param obj
     * @param planType
     */
    protected void copyPropertiesToVO(Object req, Object obj, String planType) {
        copyPropertiesToVO(req, obj, planType, IGNORE_DATE[0], IGNORE_DATE[1]);
    }

    /**
     * 参数复制 toVo
     *
     * @param req
     * @param obj
     * @param planType
     * @param ignoreStartDate
     * @param ignoreEndDate
     */
    protected void copyPropertiesToVO(Object req, Object obj, String planType, String ignoreStartDate, String ignoreEndDate) {
        BeanUtil.copyProperties(req, obj, ignoreStartDate, ignoreEndDate);
        ReflectUtil.setFieldValue(obj, ignoreStartDate, DateUtil.format(Convert.toDate(ReflectUtil.getFieldValue(req, ignoreStartDate)), DatePattern.NORM_DATE_PATTERN));
        ReflectUtil.setFieldValue(obj, ignoreEndDate, DateUtil.format(Convert.toDate(ReflectUtil.getFieldValue(req, ignoreEndDate)), DatePattern.NORM_DATE_PATTERN));
    }

    private static RemoteUserService remoteUserService;

    public static void setRemoteUserService(ApplicationContext context) {
        remoteUserService = context.getBean(RemoteUserService.class);
    }

    /**
     * 类型转换
     *
     * @param t 原对象
     * @param v 目标对象类
     * @return 目标对象
     */
    public V convert(T t, Class<V> v, String planType) {
        V obj = newInstance(v);
        copyPropertiesToVO(t, obj, planType);
        return obj;
    }

    /**
     * 类型转换
     *
     * @param t 原对象
     * @param v 目标对象类
     * @return 目标对象
     */
    public V convert(T t, Class<V> v) {
        V obj = newInstance(v);
        BeanUtil.copyProperties(t, obj);
        return obj;
    }

    /**
     * 类型转换
     *
     * @param t 原对象
     * @param v 目标对象类
     * @return 目标对象
     */
    public V convert(T t, Class<V> v, String planType, String ignoreStartDate, String ignoreEndDate) {
        V obj = newInstance(v);
        copyPropertiesToVO(t, obj, planType, ignoreStartDate, ignoreEndDate);
        return obj;
    }


    private V newInstance(Class<V> v) {
        try {
            Object obj = v.getDeclaredConstructor().newInstance();
            return (V) obj;
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
                 NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 类型转换填充创建人名称
     *
     * @param t 原对象
     * @param v 目标对象类
     * @return 目标对象
     */
    public V convertWithUser(T t, Class<V> v) {
        V obj = convert(t, v);
        setUser(t, obj);
        return obj;
    }

    /**
     * 类型转换填充创建人名称
     *
     * @param t 原对象
     * @param v 目标对象类
     * @return 目标对象
     */
    public V convertWithUser(T t, Class<V> v, String planType) {
        V obj = convert(t, v, planType);
        setUser(t, obj);
        return obj;
    }


    /**
     * 类型转换填充创建人名称
     *
     * @param t 原对象
     * @param v 目标对象类
     * @return 目标对象
     */
    public V convertWithUser(T t, Class<V> v, String planType, String ignoreStartDate, String ignoreEndDate) {
        V obj = convert(t, v, planType, ignoreStartDate, ignoreEndDate);
        setUser(t, obj);
        return obj;
    }

    private void setUser(T t, V obj) {
        Long createUserId = Convert.toLong(ReflectUtil.getFieldValue(t, "createUserId"), -1L);
        if (createUserId > -1) {
            LoginUser loginUser = remoteUserService.getUserInfoById(createUserId);
            if (loginUser != null) {
                ReflectUtil.setFieldValue(obj, "createUserName", loginUser.getUsername());
            }
        }
    }


    /**
     * 批量类型转换
     *
     * @param tList 原对象集合
     * @param v     目标对象类
     * @param fill  是否填充创建人名称
     * @return 目标对象
     */
    public List<V> convert(Collection<T> tList, Class<V> v, boolean fill) {
        List<V> vList = new ArrayList<>(tList.size());
        Set<Long> idList = new HashSet<>();
        for (T t : tList) {
            V v1 = newInstance(v);
            BeanUtil.copyProperties(t, v1);
            Long createUserId = Convert.toLong(ReflectUtil.getFieldValue(v1, "createUserId"), -1L);
            if (createUserId > -1) {
                idList.add(createUserId);
            }
            vList.add(v1);
        }
        if (fill && CollUtil.isNotEmpty(idList)) {
            List<LoginUser> loginUserList = remoteUserService.getUserListByIdList(idList);
            if (CollUtil.isNotEmpty(loginUserList)) {
                Map<Long, String> userNameMap = loginUserList.stream().collect(Collectors.toMap(LoginUser::getUserId, LoginUser::getUsername));
                for (V v1 : vList) {
                    Long createUserId = Convert.toLong(ReflectUtil.getFieldValue(v1, "createUserId"), -1L);
                    if (createUserId > -1) {
                        ReflectUtil.setFieldValue(v1, "createUserName", userNameMap.get(createUserId));
                    }
                }
            }
        }
        return vList;
    }
}
